
#include <string.h>
#include "main.h"
#include "octospi.h"
#include "psram.h"

void MPU_Config(void);

int OSPI_NORPSRAM_Reset(void)
{
  OSPI_RegularCmdTypeDef sCmd;
  memset(&sCmd, 0, sizeof(sCmd));
/////////////////////////////////////////////////////////////////////////////////////
// QSPI Reset
  sCmd.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
  sCmd.FlashId = HAL_OSPI_FLASH_ID_1;

  sCmd.InstructionMode = HAL_OSPI_INSTRUCTION_4_LINES;
  sCmd.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
  sCmd.Instruction = 0x66;

  if (HAL_OSPI_Command(&hospi1, &sCmd, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  {
    return OSPI_ERROR;
  }

  sCmd.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
  sCmd.FlashId = HAL_OSPI_FLASH_ID_1;

  sCmd.InstructionMode = HAL_OSPI_INSTRUCTION_4_LINES;
  sCmd.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
  sCmd.Instruction = 0x99;

  if (HAL_OSPI_Command(&hospi1, &sCmd, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  {
    return OSPI_ERROR;
  }
/////////////////////////////////////////////////////////////////////////////////////
// SPI Reset
  sCmd.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
  sCmd.FlashId = HAL_OSPI_FLASH_ID_1;

  sCmd.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
  sCmd.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
  sCmd.Instruction = 0x66;

  if (HAL_OSPI_Command(&hospi1, &sCmd, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  {
    return OSPI_ERROR;
  }

  sCmd.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
  sCmd.FlashId = HAL_OSPI_FLASH_ID_1;

  sCmd.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
  sCmd.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
  sCmd.Instruction = 0x99;

  if (HAL_OSPI_Command(&hospi1, &sCmd, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  {
    return OSPI_ERROR;
  }

  return OSPI_OK;
}

int OSPI_NORPSRAM_QSPI(void)
{
  OSPI_RegularCmdTypeDef sCmd;
  memset(&sCmd, 0, sizeof(sCmd));

  sCmd.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
  sCmd.FlashId = HAL_OSPI_FLASH_ID_1;

  sCmd.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
  sCmd.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
  sCmd.Instruction = 0x35;

  if (HAL_OSPI_Command(&hospi1, &sCmd, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  {
    return OSPI_ERROR;
  }
  
  return OSPI_OK;
}

int OSPI_NORPSRAM_WRAP(void)
{
  OSPI_RegularCmdTypeDef sCmd;
  memset(&sCmd, 0, sizeof(sCmd));

  sCmd.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
  sCmd.FlashId = HAL_OSPI_FLASH_ID_1;

  sCmd.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
  sCmd.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
  sCmd.Instruction = 0xc0;

  if (HAL_OSPI_Command(&hospi1, &sCmd, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  {
    return OSPI_ERROR;
  }
  
  return OSPI_OK;
}

int OSPI_NORPSRAM_ID(uint8_t *v)
{
  OSPI_RegularCmdTypeDef sCmd;
  memset(&sCmd, 0, sizeof(sCmd));

  sCmd.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
  sCmd.FlashId = HAL_OSPI_FLASH_ID_1;

  sCmd.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
  sCmd.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
  sCmd.Instruction = 0x9f;

  sCmd.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
  sCmd.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
  sCmd.Address = 0;

  sCmd.DataMode = HAL_OSPI_DATA_1_LINE;
  sCmd.DummyCycles = 0;
  sCmd.NbData = 8;

  if (HAL_OSPI_Command(&hospi1, &sCmd, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  {
    return OSPI_ERROR;
  }

  if (HAL_OSPI_Receive(&hospi1, (uint8_t *)v, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  {
    return OSPI_ERROR;
  }

  return OSPI_OK;
}

int OSPI_NORPSRAM_WRITE(uint32_t addr, void *buf, uint32_t sz)
{
  OSPI_RegularCmdTypeDef sCmd;
  memset(&sCmd, 0, sizeof(sCmd));

  sCmd.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
  sCmd.FlashId = HAL_OSPI_FLASH_ID_1;
  sCmd.DQSMode = HAL_OSPI_DQS_ENABLE;
  sCmd.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;

  sCmd.InstructionMode = HAL_OSPI_INSTRUCTION_4_LINES;
  sCmd.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
  sCmd.Instruction = 0x38; // write 0x38

  sCmd.AddressMode = HAL_OSPI_ADDRESS_4_LINES;
  sCmd.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
  sCmd.Address = addr;

  sCmd.DataMode = HAL_OSPI_DATA_4_LINES;
  sCmd.DummyCycles = 0;
  sCmd.NbData = sz;

  if (HAL_OSPI_Command(&hospi1, &sCmd, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  {
    return OSPI_ERROR;
  }

  if (HAL_OSPI_Transmit(&hospi1, (uint8_t *)buf, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 
  {
    return OSPI_ERROR;
  }

  return OSPI_OK;
}

int OSPI_NORPSRAM_READ(uint32_t addr, void *buf, uint32_t sz)
{
  OSPI_RegularCmdTypeDef sCmd;
  memset(&sCmd, 0, sizeof(sCmd));

  sCmd.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
  sCmd.FlashId = HAL_OSPI_FLASH_ID_1;
  sCmd.DQSMode = HAL_OSPI_DQS_DISABLE;
  sCmd.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;

  sCmd.InstructionMode = HAL_OSPI_INSTRUCTION_4_LINES;
  sCmd.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
  sCmd.Instruction = 0xeb; // read 0xeb

  sCmd.AddressMode = HAL_OSPI_ADDRESS_4_LINES;
  sCmd.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
  sCmd.Address = addr;

  sCmd.DataMode = HAL_OSPI_DATA_4_LINES;
  sCmd.DummyCycles = 6;
  sCmd.NbData = sz;

  if (HAL_OSPI_Command(&hospi1, &sCmd, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  {
    return OSPI_ERROR;
  }

  if (HAL_OSPI_Receive(&hospi1, (uint8_t *)buf, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 
  {
    return OSPI_ERROR;
  }

  return OSPI_OK; 
}

int OSPI_NORPSRAM_MemoryMapped(void)
{
  OSPI_RegularCmdTypeDef sCmd;
  OSPI_MemoryMappedTypeDef sMapCfg;
  memset(&sCmd, 0, sizeof(sCmd));
  memset(&sMapCfg, 0, sizeof(sMapCfg));

  HAL_MPU_Disable();

  sCmd.OperationType = HAL_OSPI_OPTYPE_READ_CFG;
  sCmd.FlashId = HAL_OSPI_FLASH_ID_1;
  sCmd.DQSMode = HAL_OSPI_DQS_DISABLE;
  sCmd.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;

  sCmd.InstructionMode = HAL_OSPI_INSTRUCTION_4_LINES;
  sCmd.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
  sCmd.Instruction = 0xeb; // write 0x38

  sCmd.AddressMode = HAL_OSPI_ADDRESS_4_LINES;
  sCmd.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
  sCmd.Address = 0;

  sCmd.DataMode = HAL_OSPI_DATA_4_LINES;
  sCmd.DummyCycles = 6;
  sCmd.NbData = 1;

  if (HAL_OSPI_Command(&hospi1, &sCmd, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  {
    return OSPI_ERROR;
  }

  sCmd.OperationType = HAL_OSPI_OPTYPE_WRITE_CFG;
  sCmd.DQSMode = HAL_OSPI_DQS_ENABLE;
  sCmd.Instruction = 0x38; // read 0xeb
  sCmd.DummyCycles = 0;
  sCmd.NbData = 1;

  if (HAL_OSPI_Command(&hospi1, &sCmd, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  {
    return OSPI_ERROR;
  }

  sMapCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_DISABLE;
  //sMapCfg.TimeOutPeriod = 1;
  if (HAL_OSPI_MemoryMapped(&hospi1, &sMapCfg) != HAL_OK)
  {
    return OSPI_ERROR;
  }

  MPU_Config();
  return OSPI_OK; 
}
